
package com.be.beadmin.design.impl;

import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.basicData.dto.output.UserEx;
import com.be.beadmin.basicData.service.UserService;
import com.be.beadmin.common.entity.PageEntity;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaQueryBuilder;
import com.be.beadmin.common.utils.JpaQueryBuilderNew;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.design.dto.input.ProductDrawingInfoDto;
import com.be.beadmin.design.dto.output.ProductDrawingInfoEx;
import com.be.beadmin.design.entity.DrawingReview;
import com.be.beadmin.design.entity.ProductBomOverview_;
import com.be.beadmin.design.entity.ProductDrawingInfo;
import com.be.beadmin.design.entity.ProductDrawingInfo_;
import com.be.beadmin.design.mapper.ProductDrawingInfoMapper;
import com.be.beadmin.design.mapper.ProductDrawingInfoMapperEx;
import com.be.beadmin.design.repository.DrawingReviewRepository;
import com.be.beadmin.design.repository.ProductDrawingInfoRepository;
import com.be.beadmin.design.service.ProductDrawingInfoService;
import com.be.beadmin.project.Util.MinioUtil;
import com.be.beadmin.project.dto.input.BatchProductDto;
import com.be.beadmin.project.entity.BatchProduct;
import com.be.beadmin.project.entity.Info;
import com.be.beadmin.project.entity.TeamInfo;
import com.be.beadmin.project.mapper.BatchProductMapper;
import com.be.beadmin.project.repository.BatchProductRepository;
import com.be.beadmin.project.repository.InfoRepository;
import com.be.beadmin.project.repository.ProductInfoRepository;
import com.be.beadmin.project.repository.TeamInfoRepository;
import com.be.beadmin.project.service.BatchProductService;
import com.be.beadmin.service.entity.NotifyInfo;
import com.be.beadmin.service.repository.NotifyInfoRepository;
import com.be.beadmin.service.repository.NotifyTemplateInfoRepository;
import com.be.beadmin.service.service.NotifyTemplateInfoService;
import com.be.beadmin.service.service.SerialNumberService;
import com.be.beadmin.service.util.DateUtil;
import io.minio.errors.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
* @description 服务实现
* @author zmy
* @date 2023-02-16
**/
@Service
@RequiredArgsConstructor
public class ProductDrawingInfoServiceImpl implements ProductDrawingInfoService {

    @Autowired
    private  ProductDrawingInfoRepository productDrawingInfoRepository;
    @Autowired
    private  ProductDrawingInfoMapper productDrawingInfoMapper;
    @Autowired
    private  ProductDrawingInfoMapperEx productDrawingInfoExMapper;

    @Autowired
    private ProductDrawingInfoService productDrawingInfoService;
    @Autowired
    private SerialNumberService serialNumberService;

    @Autowired
    private UserService userService;
    @Autowired
    private BatchProductRepository batchProductRepository;

    @Autowired
    private BatchProductMapper batchProductMapper;
    @Autowired
    private BatchProductService batchProductService;
    MinioUtil minioUtil = new MinioUtil();

    @Autowired
    private final ProductInfoRepository productInfoRepository;
    @Autowired
    private  DrawingReviewRepository drawingReviewRepository;


    @Autowired
    private NotifyTemplateInfoService notifyTemplateInfoService;

    @Autowired
    private NotifyTemplateInfoRepository notifyTemplateInfoRepository;

    @Autowired
    private NotifyInfoRepository notifyInfoRepository;

    @Autowired
    private TeamInfoRepository teamInfoRepository;

    @Autowired
    private InfoRepository infoRepository;


    @Override
    public Page<ProductDrawingInfoEx> getProductDrawingInfoByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<ProductDrawingInfo> page = productDrawingInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 = JpaQueryBuilderNew.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(ProductDrawingInfo_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(ProductDrawingInfo_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<ProductDrawingInfoEx> page1 = page.map(productDrawingInfoExMapper::toEntity);
            return page1;

    }

    @Override
    public void addProductDrawingInfo(ProductDrawingInfoDto productDrawingInfoDto) {
            ProductDrawingInfo result = productDrawingInfoRepository.findProductDrawingInfoByIdAndDelete(productDrawingInfoDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("ProductDrawingInfo不存在,请重新查询");
            }
            ProductDrawingInfo productDrawingInfo = productDrawingInfoMapper.toEntity(productDrawingInfoDto);
            productDrawingInfoRepository.save(productDrawingInfo);
    }

    @Override
    public void updateProductDrawingInfo(ProductDrawingInfoDto productDrawingInfoDto) {
            ProductDrawingInfo productDrawingInfo = productDrawingInfoRepository.findProductDrawingInfoById(productDrawingInfoDto.getId());
            productDrawingInfo = productDrawingInfoMapper.toEntity(productDrawingInfoDto);
            productDrawingInfoRepository.save(productDrawingInfo);
    }


    @Override
    public void delProductDrawingInfo(String id) {
        ProductDrawingInfo productDrawingInfo = productDrawingInfoRepository.findProductDrawingInfoById(id);
        productDrawingInfo.setDelete(1);
        productDrawingInfoRepository.save(productDrawingInfo);

        // 若删除的是 【电气原理图】【箱柜接线表】,则需要对batchProduct上传字段做修改
        BatchProduct batchProduct = batchProductRepository.findBatchProductByProductCodeAndDelete(productDrawingInfo.getProductCode(), 0);
        if(productDrawingInfo.getCategory().equals("电气原理图")) batchProduct.setIsElectDrawingUploaded(batchProduct.getIsElectDrawingUploaded()-1);
        if(productDrawingInfo.getCategory().equals("箱柜接线表")) batchProduct.setIsWireFileUploaded(batchProduct.getIsWireFileUploaded()-1);

        if(batchProduct.getIsWireFileUploaded() <=0 || batchProduct.getIsElectDrawingUploaded() <= 0){
            batchProduct.setIsDrawingUploaded(0);
        }
        batchProductRepository.save(batchProduct);

        // 若该图纸已提交审批，同时删除审批
        DrawingReview review = drawingReviewRepository.findDrawingReviewByDrawingIdAndDelete(id, 0);
        if (review != null) {
            review.setDelete(1);
            drawingReviewRepository.save(review);
        }
    }

    @Override
    public void delProductDrawingInfos (List<String> ids) { }


    //上传/变更图纸

    // done  1. 柜体提交审核后对图纸status进行更改
    public void uploadDrawing(String productCode, MultipartFile[] multipartFiles,  String drawingSpec,String bucketName,String category) throws Exception {

        //  Done
        //  1.校验是否存在未审批的文件，若有则无法上传；无则进行step2
        //  2. 校验是新增还是变更， 若是新增默认版本为1，底色为黄；变更则进行版本递增。二者均审核通过后立即生效（最高版本+审核通过）。

        long now = System.currentTimeMillis();

        BatchProduct batchProductById = batchProductRepository.findBatchProductByProductCodeAndDelete(productCode, 0);

        System.out.println(System.currentTimeMillis()-now);

        for (MultipartFile multipartFile : multipartFiles) {
            String fileName = multipartFile.getOriginalFilename();

            long now1 = System.currentTimeMillis();
            List<ProductDrawingInfo> list = productDrawingInfoRepository.findProductDrawingInfosByProductCodeAndCategoryAndDrawingNameAndDelete(productCode, category, fileName, 0);
            System.out.println(System.currentTimeMillis()-now1);

            String projectCode = batchProductById.getProductCode().substring(0, batchProductById.getProductCode().indexOf("."));
            String drawingSequence = System.currentTimeMillis()+fileName;

            long now3 = System.currentTimeMillis();
            minioUtil.uploadFile(multipartFile, drawingSequence, bucketName);
            System.out.println("文件上传:"+ (System.currentTimeMillis()-now3));

            ProductDrawingInfo productDrawingInfo = new ProductDrawingInfo();
            productDrawingInfo.setProductCode(productCode);
            productDrawingInfo.setDrawingSpec(drawingSpec);
            productDrawingInfo.setDrawingSequence(drawingSequence);
//            productDrawingInfo.setDrawingUrl(previewFileUrl);
            productDrawingInfo.setDrawingName(fileName);
            productDrawingInfo.setCategory(category);
            productDrawingInfo.setIsActive(0);
            productDrawingInfo.setChangeStatus(0);

            if (list.isEmpty()) {
                // 新增逻辑: 图纸编号递增
                int i = productDrawingInfoRepository.countNextDrawCode(productCode);
                productDrawingInfo.setDrawingCode(projectCode + "." + "003." + String.format("%03d", i + 1));
                productDrawingInfo.setVersion("1.0");
                productDrawingInfo.setChangeOrAdd("1");
                productDrawingInfoRepository.save(productDrawingInfo);

            } else {

                // 存在新增或变更的相同类型文件，覆盖
                List<ProductDrawingInfo> filerList = list.stream().filter(s -> !s.getChangeOrAdd().equals("0")).peek(s -> {
                    s.setDrawingSpec(drawingSpec);
//                    s.setDrawingUrl(previewFileUrl);
                }).collect(Collectors.toList());

                if (!filerList.isEmpty()){
                    productDrawingInfoRepository.saveAll(filerList);
                    continue;
                }

                // 变更逻辑:版本号递增
                ProductDrawingInfo maxVersionInfo = list.stream().max(new Comparator<ProductDrawingInfo>() {
                    @Override
                    public int compare(ProductDrawingInfo o1, ProductDrawingInfo o2) {
                        float num1 = Float.parseFloat(o1.getVersion());
                        float num2 = Float.parseFloat(o2.getVersion());
                        if (num1 == num2) return 0;
                        return num1 > num2 ? 1 : -1;
                    }
                }).get();

                String[] splitVersion = maxVersionInfo.getVersion().split("\\.");
                String version = splitVersion[0] + "." + (Integer.parseInt(splitVersion[1]) + 1);
                productDrawingInfo.setVersion(version);
                productDrawingInfo.setDrawingCode(maxVersionInfo.getDrawingCode());
                productDrawingInfo.setChangeOrAdd("2");
                productDrawingInfoRepository.save(productDrawingInfo);
            }

            //批次柜体中修改图纸信息
            if (category.equals("电气原理图"))
                batchProductById.setIsElectDrawingUploaded(batchProductById.getIsElectDrawingUploaded()+1);
            if (category.equals("箱柜接线表"))
                batchProductById.setIsWireFileUploaded(batchProductById.getIsWireFileUploaded()+1);

            if (batchProductById.getIsElectDrawingUploaded() > 0 && batchProductById.getIsWireFileUploaded() >0){
                batchProductById.setIsDrawingUploaded(1);
            }
//            batchProductById.setDrawingTime(DateUtil.transDateFormat(new Date()));
//            batchProductById.setDrawingIsChange(1);
//            batchProductById.setDrawingId(productDrawingInfo.getDrawingCode());
            batchProductRepository.save(batchProductById);
        }
    }

    //更新图纸
    public void updateProductDrawingInfo2(String drawingId, MultipartFile multipartFile,String drawingSpec,String bucketName,String productCode) throws Exception {
        ProductDrawingInfo productDrawingInfo = productDrawingInfoRepository.findProductDrawingInfoByIdAndDelete(drawingId, 0);
        ProductDrawingInfoDto productDrawingInfoDto = productDrawingInfoMapper.toDto(productDrawingInfo);

        //BatchProduct batchProductById = batchProductRepository.findBatchProductById(batchPlanId);
        BatchProduct batchProductById = batchProductRepository.findBatchProductByProductCode(productCode);
        //如果图纸非空，则上传
        if(ObjectUtil.isNotEmpty(multipartFile)){
            String name = multipartFile.getOriginalFilename();
            String fileName = productDrawingInfo.getProductCode()+"-"+name;
            //System.out.println(fileName);
            if(fileName!=productDrawingInfo.getDrawingUrl()){
                minioUtil.removeObject(bucketName,productDrawingInfo.getDrawingUrl());
                //删除Minio中的文件
                productDrawingInfoDto.setDrawingUrl(fileName);
            }
//            SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            batchProductById.setDrawingTime(sdf.format(System.currentTimeMillis()));
            batchProductById.setDrawingTime(new Date());
            batchProductById.setDrawingIsChange(1);
            //修改批次柜体信息
            BatchProductDto batchProductDto = batchProductMapper.toDto(batchProductById);
            batchProductService.updateBatchProduct(batchProductDto);

            batchProductService.updateBatchProduct(batchProductDto);
            minioUtil.uploadFile(multipartFile,fileName,bucketName);
        }
        if(ObjectUtil.isNotEmpty(drawingSpec)){
            productDrawingInfoDto.setDrawingSpec(drawingSpec);
        }
        productDrawingInfoService.updateProductDrawingInfo(productDrawingInfoDto);
    }

//    //下载图纸
//    public void downloadProductDrawingInfo(String drawingId, String bucketName, HttpServletResponse response){
//        ProductDrawingInfo productDrawingInfoByIdAndDelete = productDrawingInfoRepository.findProductDrawingInfoByIdAndDelete(drawingId, 0);
//        minioUtil.downloadFile(bucketName,productDrawingInfoByIdAndDelete.getDrawingUrl(),response);
//    }
    //删除图纸
    public void deleteProductDrawingInfo(String id,String bucketName) throws InvalidBucketNameException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidPortException, InvalidKeyException, InvalidEndpointException, InvalidResponseException, XmlParserException, InternalException {
        //minio删除
        ProductDrawingInfo productDrawingInfoByIdAndDelete = productDrawingInfoRepository.findProductDrawingInfoByIdAndDelete(id, 0);
        minioUtil.removeObject(bucketName,productDrawingInfoByIdAndDelete.getDrawingSequence());
        //数据库信息删除
        productDrawingInfoRepository.deleteById(productDrawingInfoByIdAndDelete.getId());
    }

    /**
     * 根绝柜体id获取柜体的图纸
     *
     * @param batchProductIds
     * @return
     */
    @Override
    public List<ProductDrawingInfo> getProductDrawing(List<String> batchProductIds) {
//        List<String> productCodes = batchProductRepository.fin
//        List<ProductDrawingInfo> productDrawingInfos = productDrawingInfoRepository.findProductDrawingInfosByProductCodeAndDelete(batchProductIds,0);
        return null;
    }
    public Page<ProductDrawingInfoEx> getDrawingByBatchProductId(HttpServletRequest request,PageEntity pageEntity, String batchProductId){
        BatchProduct batchProductById = batchProductRepository.findBatchProductById(batchProductId);

        String engineer = batchProductById.getEngineer();
        UserEx userEx = userService.viewBaseInfo(request);
        String userName = userEx.getName();
        if(!(userName.equals(engineer) || userName.equals("admin"))){
            throw new RuntimeException("当前用户无权限");
        }

        String drawingCode = batchProductById.getDrawingId();
        ProductDrawingInfo productDrawingInfoByIdAndDelete = productDrawingInfoRepository.findProductDrawingInfoByDrawingCodeAndDelete(drawingCode, 0);
//        String drawingCode1 = productDrawingInfoByIdAndDelete.getDrawingCode();
        Pageable pageable = PageRequest.of(
                pageEntity.getCurrent() -1,
                pageEntity.getPageSize());
        Page<ProductDrawingInfo> page = productDrawingInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(ProductDrawingInfo_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate pre3 = criteriaBuilder.equal(root.get(ProductDrawingInfo_.DRAWING_CODE), drawingCode);
                    list.add(pre3);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(ProductBomOverview_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                }
                , pageable);
        Page<ProductDrawingInfoEx> page1 = page.map(productDrawingInfoExMapper::toEntity);
        return page1;
    }

    public void stopIsActive(String id){
        ProductDrawingInfo productDrawing = productDrawingInfoRepository.findProductDrawingInfoByIdAndDelete(id, 0);
        if(productDrawing == null){
            throw new RuntimeException("该文件不存在");
        }
        if(productDrawing.getIsActive()==0){
            throw new RuntimeException("已停用，请勿重复该操作！");
        }
        productDrawing.setIsActive(0);
        productDrawingInfoRepository.save(productDrawing);
    }
    public void updateIsActive2(String id,String productCode,String category){
        //System.out.println(id);
        List<ProductDrawingInfo> productDrawingInfos = productDrawingInfoRepository.findProductDrawingInfosByProductCodeAndCategoryAndDelete(productCode, category,0);
        for (ProductDrawingInfo p:productDrawingInfos) {
            if(p.getDelete()==1){
                continue;
            }
            //若为指定图纸，则启用，其余均停用
            if(p.getId().equals(id)){
                p.setIsActive(1);
            }else{
                p.setIsActive(0);
            }
            productDrawingInfoRepository.save(p);
        }

    }
}